.globl read_matrix

.text
# ==============================================================================
# FUNCTION: Allocates memory and reads in a binary file as a matrix of integers
#   If any file operation fails or doesn't read the proper number of bytes,
#   exit the program with exit code 1.
# FILE FORMAT:
#   The first 8 bytes are two 4 byte ints representing the # of rows and columns
#   in the matrix. Every 4 bytes afterwards is an element of the matrix in
#   row-major order.
# Arguments:
#   a0 (char*) is the pointer to string representing the filename
#   a1 (int*)  is a pointer to an integer, we will set it to the number of rows
#   a2 (int*)  is a pointer to an integer, we will set it to the number of columns
# Returns:
#   a0 (int*)  is the pointer to the matrix in memory
#
# If you receive an fopen error or eof,
# this function exits with error code 50.
# If you receive an fread error or eof,
# this function exits with error code 51.
# If you receive an fclose error or eof,
# this function exits with error code 52.
# ==============================================================================
read_matrix:

    # Prologue
    addi sp, sp, -24
    sw ra, 0(sp)
    sw s0, 4(sp)
    sw s1, 8(sp)
    sw s2, 12(sp)
    sw s3, 16(sp)
    sw s4, 20(sp)

    # save arguments
    add s1, a1, x0
    add s2, a2, x0

    # open file
    add a1, a0, x0 # string filename (char *)
    add a2, x0, x0 # set read permission '0'
    jal ra, fopen

    addi t0, x0, -1
    # if file descriptor != -1, goto file_read
    bne a0, t0, get_dim
    addi a1, x0, 50
    jal ra, exit2

get_dim:
    # save file descriptor
    add s0, a0, x0

    # allocate 8 bytes rooms
    addi a0, x0, 8
    jal ra, malloc
    # if a0 != 0, goto read_dim
    bne a0, x0, read_dim
    addi a1, x0, 48
    jal ra, exit2

read_dim:
    # read dimensions of matrix
    add a1, s0, x0
    add a2, a0, x0
    addi a3, x0, 8
    jal ra, fread
    # if a0 == a3, goto get_data
    beq a0, a3, get_data
    addi a1, x0, 51
    jal ra, exit2

get_data:
    lw s3, 0(a2) # rows of matrix
    lw s4, 4(a2) # columns of matrix
    # free dimension
    add a0, a2, x0
    jal ra, free

    # allocate rooms for matrix data
    mul a0, s3, s4
    slli a0, a0, 2
    jal ra, malloc
    # if a0 != 0, goto read_data
    bne a0, x0, read_data
    addi a1, x0, 48
    jal ra, exit2

read_data:
    # read data of matrix
    add a1, s0, x0
    add a2, a0, x0
    mul a3, s3, s4
    slli a3, a3, 2 # number = row * col * 4 bytes
    jal ra, fread
    # if a0 == a3, goto file_close
    beq a0, a3, file_close
    addi a1, x0, 51
    jal ra, exit2

file_close:
    # close the file
    add a1, s0, x0
    jal ra, fclose
    # if a0 == x0, goto end
    beq a0, x0, end
    addi a1, x0, 52
    jal ra, exit2

end:
    sw s3, 0(s1)
    sw s4, 0(s2)
    add a0, a2, x0

    # Epilogue
    lw ra, 0(sp)
    lw s0, 4(sp)
    lw s1, 8(sp)
    lw s2, 12(sp)
    lw s3, 16(sp)
    lw s4, 20(sp)
    addi sp, sp, 24

    ret
